{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cdc28c56-5631-4abf-b485-0f226962165f",
   "metadata": {},
   "source": [
    "# Tool Usage\n",
    "\n",
    "Language models are best suited for generating natural language. They don't have access to external knowledge, and may not be well suited to for computational tasks. However, we can overcome some of these limits by augmenting models with tools.\n",
    "\n",
    "## Prompting for Tool Use\n",
    "\n",
    "The first step is to prompt the model in a way that allows it make use of tools. We'll do this by providing few-shot examples of computations using eval. We can then replace these computations with their results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "85288258-3f83-46cd-9f96-d7e6a940be33",
   "metadata": {},
   "outputs": [],
   "source": [
    "import languagemodels as lm\n",
    "import re"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2c756fa4-1def-4c81-b86e-de2d2103566a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'You have eval(28 + 51) cars.'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def generate_answer_for_calculator(question):\n",
    "    return lm.do(f\"\"\"\n",
    "Answer using eval as needed.\n",
    "\n",
    "Question: I had 17 apples and get 8 more. How many apples do I have?\n",
    "Answer: You have eval(17 + 8) apples.\n",
    "\n",
    "Question: How many dogs do I have if I start with 3 and get 2 more?\n",
    "Answer: You have eval(3 + 2) dogs.\n",
    "\n",
    "Question: I had 211 books and lose 154, how many books do I have?\n",
    "Answer: You have eval(211 - 154) books.\n",
    "\n",
    "Question: If I had 253 cats and got 101 more, how many cats do I have?\n",
    "Answer: You have eval(253 + 101) cats.\n",
    "\n",
    "Question: I buy 6 oranges and had 4 to begin with. How many oranges do I have?\n",
    "Answer: You have eval(6 + 4) oranges.\n",
    "\n",
    "Question: {question}\n",
    "\"\"\".strip())\n",
    "\n",
    "reply = generate_answer_for_calculator(\"If I have 28 cars and buy 51 more, how many cars do I have?\")\n",
    "reply"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94f05290-3f42-4b46-9af6-5447f663a166",
   "metadata": {},
   "source": [
    "## Merging Tools and Results\n",
    "\n",
    "Now that we have a result from the LLM expecting tools to be used, we can use regular expressions to replace tools with their results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "179afbef-eab0-46c8-a6c9-c38f87d7570f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'You have 79 cars.'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def replace_expressions(reply):\n",
    "    # Replace \"eval(1+2)\" with 3\n",
    "    # Also replace \"eval(1+2) = 3\" with 3, as the model sometimes predicts an answer\n",
    "    expressions = re.findall('(eval\\(([ 0-9\\.+\\-/\\*]+)\\)[ =0-9\\.]*)', reply)\n",
    "\n",
    "    for exp in expressions:\n",
    "        result = eval(exp[1])\n",
    "        reply = reply.replace(exp[0].strip(), str(result))\n",
    "        \n",
    "    return reply\n",
    "\n",
    "replace_expressions(reply)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
